package com.xh.core.util;

import com.xh.bussiness.permission.bean.dto.RoleDto;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.*;

/*
 * @Author daiwei
 * @Description
 * @Date 2019/2/23 17:23
 **/
@Slf4j
public class ReflectUtils {

    public static void main(String[] args) {
        RoleDto dto=null;
        Map<String,Object> map=new HashMap<>();
        map.put("id","1231312312");
        map.put("createTime",new Date());
        map.put("createTime","`12`12234");
        dto=convertMap2Object(map,RoleDto.class);
        System.out.println(dto);
    }

    /**
     * 把MapList的数据转换成对应Bean的list集合
     * @param mapList
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> List<T> convertUnderlinMapList2List(List<Map<String, Object>> mapList, Class<T> obj){
        List<T> result=new ArrayList<>();
        try{
            for (Map<String, Object> map:mapList){
                result.add(convertUnderlineMap2Object(map,obj));
            }
        }catch (Exception ex){

        }
        return result;
    }
    /**
     * 把ResultSet的结果放到java对象中
     * <p>
     * ResultSet
     *
     * @param obj java类的class
     * @return
     */
    public static <T> T convertUnderlineMap2Object(Map<String, Object> map, Class<T> obj) {
        try {
            /**
             * 创建对象实例
             */
            T newInstance = obj.newInstance();
            for (String key : map.keySet()) {
                String name = key.toLowerCase().trim();
                name = StringUtils.underline2Fump(name);
                String substring = name.substring(0, 1);// 首字母大写
                String replace = name.replaceFirst(substring, substring.toUpperCase());
                Class<?> type = getDeclaredType(obj,name);// 获取字段类型
                if(type==null){
                    continue;
                }
                try{
                    Method method = getDeclaredMethod(obj,"set" + replace, type);
                    if(method!=null){
                        method.invoke(newInstance, map.get(key));
                    }
                }catch (Exception ex){
                    ex.printStackTrace();
                }
            }
            return newInstance;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    /**
     * 把ResultSet的结果放到java对象中
     * <p>
     * ResultSet
     *
     * @param obj java类的class
     * @return
     */
    public static <T> T convertMap2Object(Map<String, Object> map, Class<T> obj) {
        try {
            /**
             * 创建对象实例
             */
            T newInstance = obj.newInstance();
            for (String key : map.keySet()) {
                String name = key.trim();
                //name = StringUtils.underline2Fump(name);
                String substring = name.substring(0, 1);// 首字母大写
                String replace = name.replaceFirst(substring, substring.toUpperCase());
                Class<?> type = getDeclaredType(obj,name);// 获取字段类型
                if(type==null){
                    continue;
                }
                try{
                    Method method = getDeclaredMethod(obj,"set" + replace, type);
                    if(method!=null){
                        method.invoke(newInstance, map.get(key));
                    }
                }catch (Exception ex){
                    log.warn(ex.toString());
                    log.warn("convert error:"+type.getName()+","+name+","+map.get(key));
                }
            }
            return newInstance;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 递归反射获取方法
     * @param cla
     * @param methodName
     * @param parameterTypes
     * @return
     */
    public static Method getDeclaredMethod(Class cla, String methodName, Class<?>... parameterTypes) {
        Method method = null;

        for (Class<?> clazz = cla; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                method = clazz.getDeclaredMethod(methodName, parameterTypes);
                return method;
            } catch (Exception e) {
                // 这里甚么都不要做！并且这里的异常必须这样写，不能抛出去。
                // 如果这里的异常打印或者往外抛，则就不会执行clazz=clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }

        return null;
    }

    /**
     * 递归反射获取属性类型
     * @param cla
     * @param name
     * @return
     */
    public static Class<?> getDeclaredType(Class cla, String name) {

        for (Class<?> clazz = cla; clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                return clazz.getDeclaredField(name).getType();
            } catch (Exception e) {
                // 这里甚么都不要做！并且这里的异常必须这样写，不能抛出去。
                // 如果这里的异常打印或者往外抛，则就不会执行clazz=clazz.getSuperclass(),最后就不会进入到父类中了
            }
        }

        return null;
    }
}
